package com.by.gateway.service.impl;

import com.by.gateway.service.EndpointInfo;
import com.by.gateway.service.EndpointService;
import com.by.log.Logger;
import com.by.log.LoggerFactory;
import com.by.rpc.dto.ServiceInstance;
import com.by.rpc.registry.ServiceRegistry;
import com.by.gateway.config.CircuitBreakerManager;
import com.by.gateway.discovery.ServiceDiscovery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 转发服务
 * 负责根据请求路径确定目标服务，并进行参数解析和转发
 */
@Service
public class EndpointServiceImpl implements EndpointService {

    private static final Logger logger = LoggerFactory.getLogger(EndpointServiceImpl.class);

    private final ServiceDiscovery serviceDiscovery;
    private final ServiceRegistry serviceRegistry;
    private final CircuitBreakerManager circuitBreakerManager;

    // 缓存API端点信息，避免频繁查询注册中心
    private final Map<String, EndpointInfo> apiEndpointCache = new ConcurrentHashMap<>();

    @Autowired
    public EndpointServiceImpl(
            ServiceDiscovery serviceDiscovery,
            ServiceRegistry serviceRegistry,
            CircuitBreakerManager circuitBreakerManager) {
        this.serviceDiscovery = serviceDiscovery;
        this.serviceRegistry = serviceRegistry;
        this.circuitBreakerManager = circuitBreakerManager;
    }


    /**
     * 根据请求路径获取目标服务信息
     *
     * @param path 请求路径
     * @return 目标服务实例
     */
    public EndpointInfo getTargetEndpointInfo(String path, String requestMethod) {
        try {
            String cacheKey = path + ":" + requestMethod;

            EndpointInfo endpointInfo = apiEndpointCache.get(cacheKey);
            if (endpointInfo != null) {
                return endpointInfo;
            }

            // 从服务注册中心获取所有API端点信息
            Map<String, String> allApiEndpoints = serviceRegistry.getAllServices();
            if (allApiEndpoints != null && !allApiEndpoints.isEmpty()) {
                // 分别存储精确匹配和路径匹配的端点
                List<EndpointInfo> exactMatchEndpoints = new ArrayList<>();
                List<EndpointInfo> pathMatchEndpoints = new ArrayList<>();

                // 遍历所有API端点，分类存储匹配的端点
                for (Map.Entry<String, String> entry : allApiEndpoints.entrySet()) {
                    String endpointKey = entry.getKey();
                    String endpointVal = entry.getValue();

                    // 解析服务信息
                    endpointInfo = EndpointInfo.parse(endpointKey, endpointVal);
                    if (!circuitBreakerManager.isServiceAvailable(endpointInfo.getServiceName())) {
                        logger.warn("Service {} is currently unavailable due to circuit breaker", endpointInfo.getServiceName());
                        continue;
                    }

                    // 检查路径和方法是否匹配
                    if (requestMethod.equalsIgnoreCase(endpointInfo.getHttpMethod())) {
                        if (path.equals(endpointInfo.getRoutePath())) {
                            // 精确匹配
                            exactMatchEndpoints.add(endpointInfo);
                        } else if (isPathMatchEndpoint(path, endpointInfo.getRoutePath())) {
                            // 路径匹配（包含路径变量）
                            pathMatchEndpoints.add(endpointInfo);
                        }
                    }
                }

                // 优先返回精确匹配的端点
                for (EndpointInfo exactMatchEndpoint : exactMatchEndpoints) {
                    ServiceInstance instance = serviceDiscovery.getOneInstance(
                            exactMatchEndpoint.getServiceName(),
                            exactMatchEndpoint.getVersion(),
                            exactMatchEndpoint.getGroup());
                    if (instance != null) {
                        exactMatchEndpoint.setServiceInstance(instance);
                        apiEndpointCache.put(cacheKey, exactMatchEndpoint);
                        return exactMatchEndpoint;
                    }
                }

                // 如果没有精确匹配，再尝试路径匹配
                for (EndpointInfo pathMatchEndpoint : pathMatchEndpoints) {
                    ServiceInstance instance = serviceDiscovery.getOneInstance(
                            pathMatchEndpoint.getServiceName(),
                            pathMatchEndpoint.getVersion(),
                            pathMatchEndpoint.getGroup());
                    if (instance != null) {
                        pathMatchEndpoint.setServiceInstance(instance);
                        apiEndpointCache.put(cacheKey, pathMatchEndpoint);
                        return pathMatchEndpoint;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.warn("Failed to get target service by API registry: {}", e.getMessage());
        }

        return null;
    }

    /**
     * 检查请求路径是否匹配端点路径
     *
     * @param requestPath  请求路径
     * @param endpointPath 端点路径
     * @return 是否匹配
     */
    private boolean isPathMatchEndpoint(String requestPath, String endpointPath) {
        // 将端点路径中的路径变量转换为正则表达式
        String regex = endpointPath.replaceAll("\\{[^}]+\\}", "[^/]+");
        // 确保以^开头和$结尾，以进行完整匹配
        regex = "^" + regex + "$";

        return requestPath.matches(regex);
    }

    /**
     * 记录服务调用结果
     */
    public void recordServiceCallResult(String serviceName, boolean success) {
        if (success) {
            circuitBreakerManager.recordSuccess(serviceName);
        } else {
            circuitBreakerManager.recordFailure(serviceName);
        }
    }
}